package entity.map;

import java.util.List;

import entity.GameEntity;
import entity.Position;

public class FieldEntityCacheMap implements IFieldMapEntity
{
	public static Integer SIZE_CACHE_MAP = 10;
	public static Integer SIZE_TAB_CACHE_MAP = 5;
	public static Integer TTT = 2;

	protected FieldEntityMap[][] _mapCache = null;
	protected IControllerCacheMap _controller = null;
	protected Position _position = null;

	public FieldEntityCacheMap(Position pPosition, IControllerCacheMap pController)
	{
		_mapCache = new FieldEntityMap[SIZE_TAB_CACHE_MAP][SIZE_TAB_CACHE_MAP];
		_position = pPosition;
		_controller = pController;
	}
	
	public void init()
	{
		getCacheMap();
	}

	@Override
	public boolean isBlocked( Position pPosition )
	{
		boolean result = false;
		FieldEntity field = getFieldEntity( pPosition );
		if ( field != null )
		{
			result = field.isBlock();
		}
		return result;
	}

	@Override
	public void setFieldEntity( FieldEntity pFieldEntity )
	{
		Position cachePosition = calculateCachePosition( pFieldEntity.getPosition() );
		FieldEntityMap map = getCacheMap( cachePosition );
		if(map == null)
		{
			 Position posCentral = calculateCachePosition( _position );
			 int posX = -(posCentral.getX() - cachePosition.getX());
			 int posY = -(posCentral.getY() - cachePosition.getY());

				if ( posX >= -TTT && posX <= TTT && posY >= -TTT && posY <= TTT )
				{
					System.out.println("creation:"+(posX+TTT)+";"+(posY+TTT)+"<="+cachePosition.getX()+";"+cachePosition.getY());
				map = new FieldEntityMap( SIZE_CACHE_MAP, SIZE_CACHE_MAP);
				_mapCache[posX+TTT][posY+TTT] = map;		
			}		
				

		}
		 if ( map != null )
			{
				map.setFieldEntity( pFieldEntity );
			}
	

	}

	private FieldEntityMap getCacheMap( Position pPosition )
	{
		FieldEntityMap result = null;
		Position posC = calculateCachePosition( _position );
		int posX = posC.getX() - pPosition.getX();
		int posY = posC.getY() - pPosition.getY();
		if ( posX >= -TTT && posX <= TTT && posY >= -TTT && posY <= TTT )
		{
			result = _mapCache[posX+TTT][posY+TTT];			
		}
		return result;
	}

	private Position calculateCachePosition( Position pPosition )
	{
		Integer mapPositionX = pPosition.getX() / SIZE_CACHE_MAP;
		Integer mapPositionY = pPosition.getY() / SIZE_CACHE_MAP;
		return new Position( mapPositionX, mapPositionY );
	}

	private Position calculatePositionInCache( Position pPosition )
	{
		Integer mapPositionX = pPosition.getX() % SIZE_CACHE_MAP;
		Integer mapPositionY = pPosition.getY() % SIZE_CACHE_MAP;
		return new Position( mapPositionX, mapPositionY );
	}

	public FieldEntity getFieldEntity( Position pPosition )
	{
		FieldEntity result = null;
		Position cachePosition = calculateCachePosition( pPosition );
		FieldEntityMap map = getCacheMap( cachePosition );
		if ( map != null )
		{
			Position positionInCache = calculatePositionInCache( pPosition );
			result = map.getFieldEntity( positionInCache );
		}
		return result;
	}

	@Override
	public void changeMainPosition(Position pPosition) 
	{
		Position position = calculateCachePosition(  pPosition );
		if( !position.equals(_position))
		{
			decalTab(position.getX() - _position.getX(),position.getY() - _position.getY() );
			getCacheMap();
			_position = position;
		}
	}
	
	private void decalTab(int pDecalX,int pDecalY)
	{		
		if( pDecalX <= 1 && pDecalX >= -1 && pDecalY <= 1 && pDecalY >= -1)
		{
			FieldEntityMap[][] mapCache = new FieldEntityMap[SIZE_TAB_CACHE_MAP][SIZE_TAB_CACHE_MAP];
			for ( int x = 0; x < SIZE_TAB_CACHE_MAP; x++ )
			{
				for ( int y = 0; y < SIZE_TAB_CACHE_MAP; y++ )
				{
					int nx = x + pDecalX;
					int ny = y + pDecalY;					
					if( nx >= 0 && nx < SIZE_TAB_CACHE_MAP && ny >= 0 && ny < SIZE_TAB_CACHE_MAP )
					{
						System.out.println("decal:"+x+";"+y+"<="+nx+";"+ny+":"+_mapCache[nx][ny]);
						mapCache[x][y]  =_mapCache[nx][ny];
					}
				}
			}
			_mapCache = mapCache;
		}
	}
	
	private void getCacheMap()
	{
		System.out.println("*************");
		 Position posCentral = calculateCachePosition( _position );
		for ( int x = 0; x < SIZE_TAB_CACHE_MAP; x++ )
		{
			for ( int y = 0; y < SIZE_TAB_CACHE_MAP; y++ )
			{				
				if(_mapCache[x][y] == null)
				{
				_controller.getNewCache( new Position( posCentral.getX() -TTT + x ,  posCentral.getY() -TTT + y ) );
				}
			}
		}
		System.out.println("*************");
	}

	@Override
	public void addGameEntity(GameEntity pGameEntity)
	{
		// TODO Auto-generated method stub
		
	}

	@Override
	public List<GameEntity> getGameEntitys()
	{
		// TODO Auto-generated method stub
		return null;
	}
	
}
